package pers.cz.util;

import pers.cz.config.Config;

import java.util.Map;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 录制线程管理工具
 * @program: postgirl-collection-client
 * @description: ColletExecutor
 * @author: Cheng Zhi
 * @create: 2022-02-22 14:30
 **/
public class ColletExecutor {

    public static int PRODUCER_CORE_POOL_SIZE = 10;    // 核心线程数
    public static int PRODUCER_MAX_POOL_SIZE = 15;    // 最大线程池
    public static int PRODUCER_KEEP_ALIVE_TIME = 1;   // 线程等待时间
    public static int PRODUCER_MAX_BUFF_SIZE = 100;   // 缓存大小

    //private ExecutorService producerExecutor;
    private ThreadPoolExecutor  producerExecutor;

    public static ColletExecutor colletExecutor;
    // 数据类型 （接口出入参录制、sql录制）
    private int dataType;

    private ColletExecutor(Integer dataType) {
        this.dataType = dataType;
    }

    /**
     * 提交线程
     * @param generator
     */
    public void executeTask(ICollectGenerator generator) {
        this.producerExecutor.execute(generator);
    }

    /**
     * 单例模式实例化对象
     * @param dataType
     * @return
     */
    public static ColletExecutor getInstance(Integer dataType) {

        if (colletExecutor == null) {
            colletExecutor = new ColletExecutor(dataType);
            // 初始化时就开启线程池
            colletExecutor.start();
        }
        return colletExecutor;
    }

    /**
     * 初始化线程池
     */
    public void start() {
        this.startProducerExecutor();
    }

    /**
     * 初始化生产者线程池
     */
    private void startProducerExecutor() {

        // 从redis中获取线程参数
        Map<String, String> cacheMap = Config.getConfig().getsysConfig();
        Integer corePoolSize = Integer.valueOf(cacheMap.get("redis.PRODUCER_CORE_POOL_SIZE") == null? "0" : cacheMap.get("redis.PRODUCER_CORE_POOL_SIZE"));
        if(corePoolSize == null || corePoolSize.intValue() < 1) corePoolSize = PRODUCER_CORE_POOL_SIZE;

        Integer maxPoolSize = Integer.valueOf(cacheMap.get("redis.PRODUCER_MAX_POOL_SIZE") == null? "0" : cacheMap.get("redis.PRODUCER_MAX_POOL_SIZE"));
        if(maxPoolSize == null || maxPoolSize.intValue() < 1) maxPoolSize = PRODUCER_MAX_POOL_SIZE;

        Integer keepAliveTime = Integer.valueOf(cacheMap.get("redis.PRODUCER_KEEP_ALIVE_TIME") == null? "0" : cacheMap.get("redis.PRODUCER_KEEP_ALIVE_TIME"));
        if(keepAliveTime == null || keepAliveTime.intValue() < 1) keepAliveTime = PRODUCER_KEEP_ALIVE_TIME;

        BlockingQueue<Runnable> blockingQueue = new LinkedBlockingDeque<Runnable>();
        this.producerExecutor = new ThreadPoolExecutor(corePoolSize, maxPoolSize, keepAliveTime, TimeUnit.SECONDS, blockingQueue);
        this.producerExecutor.allowCoreThreadTimeOut(true);
    }

    /**
     * 线程池停止
     */
    public void stop() {

        System.out.println("调用了一次停止");
        this.stopProducerExecutor();

    }

    /**
     * 停止生产者线程池
     */
    private void stopProducerExecutor(){
        this.producerExecutor.shutdown();
        try{

            while(true){
                if(this.producerExecutor.awaitTermination(1, TimeUnit.SECONDS)){
                    System.out.println("真正停止");
                    this.producerExecutor.shutdownNow();
                    break;
                }
            }
        }catch(Exception e){
            return;
        }
    }

}
